home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’93 / HackTV & Example panel comp. / softVdig.c < prev    next >
C/C++ Source or Header  |  1993-08-18  |  30KB  |  1,127 lines

  1. /*
  2.     File:        softVdig.c
  3.  
  4.     Contains:    Software video digitzer routines
  5.  
  6.     Written by:    Peter Hoddie (mostly) and Casey King and Gary Woodcock
  7.     
  8.                 Refer to develop Issue 14, "Video Digitizing Under QuickTime",
  9.                 for details on this code.
  10.                 
  11.                 This code requires QuickTime 1.5.
  12.  
  13.     Copyright:    © 1993 by Apple Computer, Inc.
  14.  
  15. */
  16.  
  17. //-----------------------------------------------------------------------
  18. // includes
  19.  
  20. #include "softVdig.h"
  21. #include <BDC.h>
  22. #include <FixMath.h>
  23. #include <Errors.h>
  24. #include <Packages.h>
  25. #include <Fonts.h>
  26. #include <Memory.h>
  27. #include <ToolUtils.h>
  28.  
  29. //-----------------------------------------------------------------------
  30.  
  31.  
  32. #ifdef DEBUG_IT
  33. // Use this declaration when we're running linked (for debugging)
  34. pascal ComponentResult softVdig (ComponentParameters *params, Handle storage)
  35.  
  36. #else
  37.  
  38. // Use this declaration when we're a standalone component
  39. pascal ComponentResult main(ComponentParameters *params, Handle storage)
  40.  
  41. #endif DEBUG_IT
  42.  
  43. {
  44.     // This routine is the main dispatcher for the softVdig
  45.     
  46.     ComponentFunction    vdigProc = 0;
  47.     OSErr err = 0;
  48.  
  49.     if (params->what < 0) {
  50.         switch(params->what) {
  51.             case kComponentOpenSelect:                vdigProc = vdigOpen; break;
  52.             case kComponentCloseSelect:                vdigProc = vdigClose; break;
  53.             case kComponentCanDoSelect:                vdigProc = vdigCanDo; break;
  54.             case kComponentVersionSelect:            vdigProc = vdigVersion; break;
  55.         }
  56.     }
  57.     else {
  58.         switch (params->what) {
  59.             case kSelectVDGetMaxSrcRect:            vdigProc = vdigGetMaxSrcRect; break;
  60.             case kSelectVDGetActiveSrcRect:            vdigProc = vdigGetActiveSrcRect; break;
  61.             case kSelectVDSetDigitizerRect:            vdigProc = vdigSetDigitizerRect; break;
  62.             case kSelectVDGetDigitizerRect:            vdigProc = vdigGetDigitizerRect; break;
  63.             case kSelectVDUseThisCLUT:                vdigProc = vdigUseThisCLUT; break;
  64.             case kSelectVDGrabOneFrame:                vdigProc = vdigGrabOneFrame; break;
  65.             case kSelectVDGetMaxAuxBuffer:            vdigProc = vdigGetMaxAuxBuffer; break;
  66.             case kSelectVDGetDigitizerInfo:            vdigProc = vdigGetDigitizerInfo; break;
  67.             case kSelectVDGetCurrentFlags :            vdigProc = vdigGetCurrentFlags; break;
  68.             case kSelectVDSetPlayThruDestination:    vdigProc = vdigSetPlayThruDestination; break;
  69.             case kSelectVDSetBrightness :            vdigProc = vdigSetBrightness; break;
  70.             case kSelectVDGetBrightness :            vdigProc = vdigGetBrightness; break;    
  71.             case kSelectVDSetContrast :                vdigProc = vdigSetContrast; break;            
  72.             case kSelectVDSetHue :                    vdigProc = vdigSetHue; break;
  73.             case kSelectVDSetSaturation :            vdigProc = vdigSetSaturation; break;
  74.             case kSelectVDSetSharpness :            vdigProc = vdigSetSharpness; break;
  75.             case kSelectVDGetContrast :                vdigProc = vdigGetContrast; break;
  76.             case kSelectVDGetHue :                    vdigProc = vdigGetHue; break;
  77.             case kSelectVDGetSaturation :            vdigProc = vdigGetSaturation; break;
  78.             case kSelectVDGetSharpness :            vdigProc = vdigGetSharpness; break;
  79.             case kSelectVDSetBlackLevelValue :        vdigProc = vdigSetBlackLevel; break;
  80.             case kSelectVDGetBlackLevelValue :        vdigProc = vdigGetBlackLevel; break;
  81.             case kSelectVDSetWhiteLevelValue :        vdigProc = vdigSetWhiteLevel; break;
  82.             case kSelectVDGetWhiteLevelValue :        vdigProc = vdigGetWhiteLevel; break;
  83.             case kSelectVDGetVideoDefaults :        vdigProc = vdigGetVideoDefaults; break;    
  84.             case kSelectVDSetPlayThruOnOff:            vdigProc = vdigSetPlayThruOnOff; break;
  85.             case kSelectVDPreflightDestination:        vdigProc = vdigPreflightDestination; break;
  86.             case kSelectVDSetupBuffers:                vdigProc = vdigSetupBuffers; break;
  87.             case kSelectVDGrabOneFrameAsync:        vdigProc = vdigGrabOneFrameAsync; break;
  88.             case kSelectVDDone:                        vdigProc = vdigDone; break;
  89.             case kSelectVDGetNumberOfInputs:        vdigProc = vdigGetNumberOfInputs; break;
  90.             case kSelectVDGetInputFormat:            vdigProc = vdigGetInputFormat; break;
  91.             case kSelectVDSetInput:                    vdigProc = vdigSetInput; break;
  92.             case kSelectVDGetInput:                    vdigProc = vdigGetInput; break;
  93.             case kSelectVDSetCompression:            vdigProc = vdigSetCompression; break;
  94.             case kSelectVDCompressOneFrameAsync:    vdigProc = vdigCompressOneFrameAsync; break;
  95.             case kSelectVDCompressDone:                vdigProc = vdigCompressDone; break;
  96.             case kSelectVDReleaseCompressBuffer:    vdigProc = vdigReleaseCompressBuffer; break;
  97.             case kSelectVDGetImageDescription:        vdigProc = vdigGetImageDescription; break;
  98.             case kSelectVDResetCompressSequence:    vdigProc = vdigResetCompressSequence; break;
  99.             case kSelectVDSetCompressionOnOff:        vdigProc = vdigSetCompressionOnOff; break;
  100.             case kSelectVDGetCompressionTypes:        vdigProc = vdigGetCompressionTypes; break;
  101.             case kSelectVDSetTimeBase:                vdigProc = vdigSetTimeBase; break;
  102.             case kSelectVDSetFrameRate:                vdigProc = vdigSetFrameRate; break;
  103.             case kSelectVDGetDMADepths:                vdigProc = vdigGetDMADepths; break;
  104.             case kSelectVDGetPreferredTimeScale:    vdigProc = vdigGetPreferredTimeScale; break;
  105.  
  106.             default:
  107.                         err = digiUnimpErr;
  108.                         break;
  109.         }
  110.     }
  111.  
  112.     if (vdigProc) {
  113.         err = CallComponentFunctionWithStorage((Handle)storage, params, vdigProc);
  114.         
  115.     // kck - for debug only to catch calls that fail
  116.     if (((params->what != kSelectVDSetFrameRate) && 
  117.             (params->what != kSelectVDCompressDone) && 
  118.             (params->what != kSelectVDGetMaxAuxBuffer) &&
  119.             (params->what != kSelectVDUseThisCLUT) && 
  120.             (params->what != kSelectVDSetCompressionOnOff)
  121.             ) && err ) {
  122.             return err;
  123.         }
  124.         return err;
  125.     }
  126.  
  127. bail:
  128.     return err;
  129. }
  130.  
  131. #ifdef DEBUG_IT
  132. Component RegisterSoftVdig(void)
  133. {
  134.     ComponentDescription foo;
  135.     Component fooey;
  136.     Handle name;
  137.  
  138.       foo.componentType = videoDigitizerComponentType;
  139.       foo.componentSubType = 'soft';
  140.       foo.componentManufacturer = 'jph ';
  141.       foo.componentFlags = 0L;
  142.       foo.componentFlagsMask = 0L;
  143.  
  144.     PtrToHand ((Ptr)"\psoftVdig (Linked)", &name, 18);
  145.     fooey = RegisterComponent (&foo, (void *)softVdig, 0, name, 0, 0);
  146.     DisposHandle (name);
  147.     SetDefaultComponent (fooey, defaultComponentAnyFlagsAnyManufacturerAnySubType);
  148.  
  149.     return fooey;
  150. }
  151. #endif DEBUG_IT
  152.  
  153. pascal ComponentResult vdigOpen(vdigGlobals storage, ComponentInstance self)
  154. {
  155.     OSErr err;
  156.  
  157.     if (CountComponentInstances((Component)self) > (short)gMaxSoftVdigCount)
  158.         return(-1);
  159.  
  160.     storage = (vdigGlobals)NewHandleClear(sizeof(vdigGlobalsRecord));
  161.     if (err = MemError()) goto bail;
  162.     (**storage).self = self;
  163.     SetComponentInstanceStorage(self, (Handle)storage);
  164.     SetComponentInstanceA5(self, *(long *)0x904);
  165.  
  166.     // Initialize some of the global storage members
  167.     err = vdigGetMaxSrcRect(storage, ntscIn, &(**storage).maxSrcRect);
  168.     (**storage).digiRect = (**storage).maxSrcRect;
  169.     (**storage).pendingAsyncBuffer = -1;
  170.     err = vdigGetVideoDefaults(storage,
  171.                              &(**storage).blackLevel, &(**storage).whiteLevel,
  172.                             &(**storage).brightness, &(**storage).hue, &(**storage).saturation,
  173.                             &(**storage).contrast, &(**storage).sharpness);
  174.  
  175. // Initialize two additional softvdig configurable items
  176.     (**storage).gAttachedGDevice = 0;
  177.     SetRect(&(**storage).gAuxBufferRect,0,0,300,300);
  178.  
  179.  
  180. bail:
  181.     return(err);
  182. }
  183.  
  184. pascal ComponentResult vdigClose(vdigGlobals storage, ComponentInstance self)
  185. {
  186.     if (storage) {
  187.         if ((**storage).tempPort)
  188.             DisposeGWorld((**storage).tempPort);
  189.  
  190.         if ((**storage).auxBuffer)
  191.             DisposeGWorld((**storage).auxBuffer);
  192.  
  193.         if ((**storage).bufferList)
  194.             DisposHandle((Handle)(**storage).bufferList);
  195.  
  196.         if ((**storage).clipRgn)
  197.             DisposeRgn((**storage).clipRgn);
  198.  
  199.         tossCompressStuff(storage);
  200.  
  201.         DisposeHandle((Handle)storage);
  202.     }
  203.  
  204.     return noErr;
  205. }
  206.  
  207. pascal ComponentResult vdigCanDo(vdigGlobals storage, short ftnNumber)
  208. {
  209.     return (ftnNumber <= kvdigSelectors) && (ftnNumber >= kComponentVersionSelect);
  210. }
  211.  
  212. pascal ComponentResult vdigVersion(vdigGlobals storage)
  213. {
  214.     return (vdigInterfaceRev<<16) | 1;
  215. }
  216.  
  217. pascal VideoDigitizerError vdigGetMaxSrcRect(vdigGlobals storage, short inputStd, Rect *maxSrcRect)
  218. {
  219. long    error = noErr;
  220.  
  221.     if (inputStd == ntscIn)            // softvdig supports only NTSC
  222.         SetRect(maxSrcRect, 0, 0, kMaxHorNTSCIn, kMaxVerNTSCIn + kVerBlank);
  223.     else
  224.         error = paramErr;
  225.     if (!error) (**storage).maxSrcRect = *maxSrcRect;
  226.  
  227.     return error;
  228. }
  229.  
  230. pascal VideoDigitizerError vdigGetActiveSrcRect(vdigGlobals storage, short inputStd, Rect *activeSrcRect)
  231. {
  232.     *activeSrcRect = (**storage).maxSrcRect;
  233.  
  234.     return noErr;
  235. }
  236.  
  237. pascal VideoDigitizerError vdigSetDigitizerRect(vdigGlobals storage, Rect *digiRect)
  238. {
  239.     Rect tempR;
  240.  
  241.     // can't be empty
  242.     if (!digiRect || EmptyRect(digiRect))
  243.         return(paramErr);
  244.  
  245.     // they must intersect
  246.     if (!SectRect(digiRect, &(**storage).maxSrcRect, &tempR))
  247.         return(paramErr);
  248.  
  249.     // completely...
  250.     if (!EqualRect(digiRect, &tempR))
  251.         return(paramErr);
  252.  
  253.     (**storage).digiRect = *digiRect;
  254.  
  255.     return noErr;
  256. }
  257.  
  258. pascal VideoDigitizerError vdigGetDigitizerRect(vdigGlobals storage, Rect *digiRect)
  259. {
  260.     *digiRect = (**storage).digiRect;
  261.  
  262.     return noErr;
  263. }
  264.  
  265. pascal VideoDigitizerError vdigUseThisCLUT(vdigGlobals storage, CTabHandle colorTableHandle)
  266. {
  267.     return digiUnimpErr;
  268. }
  269.  
  270. void makeOffscreen(vdigGlobals storage)
  271. {
  272.     OSErr err;
  273.     GWorldPtr tempPort;
  274.     Rect r;
  275.  
  276.     tossOffscreen(storage);
  277.  
  278.     if (!(**storage).playThruPixMap) return;
  279.  
  280.     SetRect(&r, 0, 0, 4, 4);
  281.     err = NewGWorld(&tempPort, (**(**storage).playThruPixMap).pixelSize, &r, 0, 0, 0);
  282.     if (err) return;
  283.  
  284.     (**storage).tempPort = tempPort;
  285.     SetRectRgn(tempPort->visRgn, -32000, -32000, 32000, 32000);
  286. }
  287.  
  288. void tossOffscreen(vdigGlobals storage)
  289. {
  290.     if ((**storage).tempPort) {
  291.         DisposeGWorld((**storage).tempPort);
  292.         (**storage).tempPort = 0;
  293.     }
  294. }
  295.  
  296. void drawVideoFrame(vdigGlobals storage, Point where, PixMapHandle destPixMap)
  297. {
  298.     Rect destRect;
  299.     CGrafPtr savePort;
  300.     GDHandle saveGD;
  301.     PixMapHandle savePortPix;
  302.     PicHandle thePict;
  303.     Rect pictRect;
  304.     Rect clipRect;
  305.     Str255 tempStr;
  306.     Point offsetClip;
  307.     RgnHandle clipRgn;
  308.  
  309.     if (!(**storage).tempPort && !(**storage).compressGW) {
  310.         makeOffscreen(storage);
  311.         if (!(**storage).tempPort)
  312.             return;
  313.     }
  314.  
  315.     destRect = (**storage).digiRect;
  316.     TransformRect(&(**storage).matrix, &destRect, 0);
  317.     OffsetRect(&destRect, -destRect.left + where.h, -destRect.top + where.v);
  318.  
  319.     GetGWorld(&savePort, &saveGD);
  320.     if ((**storage).compressGW)
  321.         SetGWorld((**storage).compressGW, 0);
  322.     else {
  323.         SetGWorld((**storage).tempPort, 0);
  324.         savePortPix = (**storage).tempPort->portPixMap;
  325.         SetPortPix(destPixMap);
  326.     }
  327.  
  328.     clipRect = (**storage).digiRect;
  329.     ClipRect(&clipRect);
  330.  
  331.     pictRect = (**storage).maxSrcRect;
  332.     thePict = OpenPicture(&pictRect);
  333.         EraseRect(&pictRect);
  334.         FrameRect(&pictRect);
  335.         InsetRect(&pictRect, 10, 10);
  336.         FrameRect(&pictRect);
  337.         InsetRect(&pictRect, 10, 10);
  338.         MoveTo(pictRect.left, (pictRect.top + pictRect.bottom) >> 1);
  339.         NumToString((**storage).frameNumber, tempStr);
  340.  
  341.         TextFont(helvetica);
  342.         TextSize((pictRect.bottom - pictRect.top) >> 2);
  343.         DrawString(tempStr);
  344.     ClosePicture();
  345.  
  346.     if (clipRgn = (**storage).clipRgn) {
  347.         offsetClip.h = where.h - (**storage).clipOrigin.h;
  348.         offsetClip.v = where.v - (**storage).clipOrigin.v;
  349.         OffsetRgn(clipRgn, offsetClip.h, offsetClip.v);
  350.         SetClip(clipRgn);
  351.     }
  352.     else {
  353.         SetRect(&clipRect, -32000, -32000, 32000, 32000);
  354.         ClipRect(&clipRect);
  355.     }
  356.  
  357.     clipRect = (**storage).maxSrcRect;
  358.     MapRect(&clipRect, &(**storage).digiRect, &destRect);
  359.     DrawPicture(thePict, &clipRect);
  360.  
  361.     KillPicture(thePict);
  362.     (**storage).frameNumber++;
  363.  
  364.     if (clipRgn) {
  365.         OffsetRgn(clipRgn, -offsetClip.h, -offsetClip.v);
  366.         SetRect(&clipRect, -32000, -32000, 32000, 32000);
  367.         ClipRect(&clipRect);
  368.     }
  369.  
  370.     if (!(**storage).compressGW)
  371.         SetPortPix(savePortPix);
  372.     SetGWorld(savePort, saveGD);
  373. }
  374.  
  375. pascal VideoDigitizerError vdigGrabOneFrame(vdigGlobals storage)
  376. {
  377.     if (!(**storage).playThruPixMap)
  378.         return badCallOrder;
  379.  
  380.     drawVideoFrame(storage, *(Point *)&((**storage).playThruRect), (**storage).playThruPixMap);
  381.  
  382.     return noErr;
  383. }
  384. pascal VideoDigitizerError vdigSetContrast(vdigGlobals storage, unsigned short *contrast)
  385. {
  386.     (**storage).contrast = *contrast;
  387.     return noErr;
  388. }
  389.  
  390. pascal VideoDigitizerError vdigGetContrast(vdigGlobals storage, unsigned short *contrast)
  391. {
  392.     *contrast = (**storage).contrast;
  393.     return noErr;
  394. }
  395.  
  396. pascal VideoDigitizerError vdigSetHue(vdigGlobals storage, unsigned short *hue) {
  397.     (**storage).hue = *hue;
  398.     return noErr;
  399. }
  400. pascal VideoDigitizerError vdigGetHue(vdigGlobals storage, unsigned short *hue)
  401. {
  402.     *hue = (**storage).hue;
  403.     return noErr;
  404. }
  405.  
  406. pascal VideoDigitizerError vdigSetBrightness(vdigGlobals storage, unsigned short *brightness)
  407. {
  408.     (**storage).brightness = *brightness;
  409.     return noErr;
  410. }
  411. pascal VideoDigitizerError vdigGetBrightness(vdigGlobals storage, unsigned short *brightness)
  412. {
  413.     *brightness = (**storage).brightness;
  414.     return noErr;
  415. }
  416.  
  417. pascal VideoDigitizerError vdigSetSaturation(vdigGlobals storage, unsigned short *saturation)
  418. {
  419.     (**storage).saturation = *saturation;
  420.     return noErr;
  421. }
  422.  
  423. pascal VideoDigitizerError vdigGetSaturation(vdigGlobals storage, unsigned short *saturation)
  424. {
  425.     *saturation = (**storage).saturation;
  426.     return noErr;
  427. }
  428. pascal VideoDigitizerError vdigSetSharpness(vdigGlobals storage, unsigned short *sharpness)
  429. {
  430.     (**storage).sharpness = *sharpness;
  431.     return noErr;
  432. }
  433.  
  434. pascal VideoDigitizerError vdigGetSharpness(vdigGlobals storage, unsigned short *sharpness)
  435. {
  436.     *sharpness = (**storage).sharpness;
  437.     return noErr;
  438. }
  439.  
  440. pascal VideoDigitizerError vdigSetBlackLevel(vdigGlobals storage, unsigned short *blackLevel)
  441. {
  442.     (**storage).blackLevel = *blackLevel;
  443.     return noErr;
  444. }
  445. pascal VideoDigitizerError vdigGetBlackLevel(vdigGlobals storage, unsigned short *blackLevel)
  446. {
  447.     *blackLevel = (**storage).blackLevel;
  448.     return noErr;
  449. }
  450. pascal VideoDigitizerError vdigSetWhiteLevel(vdigGlobals storage, unsigned short *whiteLevel)
  451. {
  452.     (**storage).whiteLevel = *whiteLevel;
  453.     return noErr;
  454. }
  455. pascal VideoDigitizerError vdigGetWhiteLevel(vdigGlobals storage, unsigned short *whiteLevel){
  456.     *whiteLevel = (**storage).whiteLevel;
  457.     return noErr;
  458. }
  459. pascal VideoDigitizerError vdigGetVideoDefaults(vdigGlobals storage,
  460.                             unsigned short *blackLevel, unsigned short *whiteLevel,
  461.                             unsigned short *brightness, unsigned short *hue, unsigned short *saturation,
  462.                             unsigned short *contrast, unsigned short *sharpness)
  463. {
  464.     (**storage).blackLevel     = 0;
  465.     (**storage).whiteLevel     = 60000;
  466.     (**storage).brightness     = 20000;
  467.     (**storage).hue         = 30000;
  468.     (**storage).saturation     = 40000;
  469.     (**storage).contrast     = 50000;
  470.     (**storage).sharpness     = 60000;
  471.     return noErr;
  472. }
  473.  
  474. pascal VideoDigitizerError vdigGetMaxAuxBuffer(vdigGlobals storage, PixMapHandle *pm, Rect *r)
  475. {
  476.     OSErr     err = noErr;
  477.  
  478.     if (!gHasAuxBuffer)
  479.         return digiUnimpErr;
  480.  
  481.     if (!(**storage).auxBuffer) {
  482.         GWorldPtr tempGW;
  483.  
  484.         err = NewGWorld(&tempGW, gAuxDepth, &(**storage).gAuxBufferRect, 0, 0, 0);
  485.         if (err) goto bail;
  486.  
  487.         LockPixels(tempGW->portPixMap);
  488.  
  489.         (**storage).auxBuffer = tempGW;
  490.     }
  491.  
  492.     if (pm) *pm = (**storage).auxBuffer->portPixMap;
  493.     if (r) *r = (**(**storage).auxBuffer->portPixMap).bounds;
  494.  
  495. bail:
  496.     return err;
  497. }
  498.  
  499. pascal VideoDigitizerError vdigGetDigitizerInfo(vdigGlobals storage, DigitizerInfo *info)
  500. {
  501.     
  502.     info->vdigType = gCanClip ? vdTypeMask : vdTypeBasic;
  503.     info->inputCapabilityFlags = digiInDoesNTSC | digiInDoesComposite | digiInDoesColor;
  504.     info->outputCapabilityFlags = gDoesDepths |
  505.                                 (gCanScale ? digiOutDoesStretch | digiOutDoesShrink : digiOutDoesQuarter | digiOutDoesSixteenth) | 
  506.                                 (gCanClip ? digiOutDoesMask : 0) |
  507.                                 (gCanDMA ? digiOutDoesHW_DMA : 0) |
  508.                                 (gDoesPlaythru ? digiOutDoesHWPlayThru : 0) |
  509.                                 (gCanAsync ? digiOutDoesAsyncGrabs : 0) |
  510.                                 (gDoesCompress ? digiOutDoesCompress : 0) |
  511.                                 ((gDoesCompress && gOnlyDoesCompress) ? digiOutDoesCompressOnly : 0)
  512.                                 ;
  513.  
  514.     info->inputCurrentFlags = info->inputCapabilityFlags;
  515.     info->inputCurrentFlags |= digiInSignalLock;
  516.     info->outputCurrentFlags = 0;
  517.     if ((**storage).gAttachedGDevice)
  518.         info->outputCurrentFlags = (**(**(**storage).gAttachedGDevice).gdPMap).pixelSize;
  519.     else {
  520.  
  521.     }
  522.  
  523.     info->slot = 0;                                // we have no slot
  524.     info->gdh = (**storage).gAttachedGDevice;
  525.     info->maskgdh = 0;                            
  526.     info->minDestHeight = gMinHeight;
  527.     info->minDestWidth = gMinWidth;
  528.     info->maxDestHeight = gMaxHeight;
  529.     info->maxDestWidth = gMaxWidth;
  530.     info->blendLevels = 0;
  531.     info->reserved = 0;
  532.     
  533.     (**storage).inputCurrentFlags  = info->inputCurrentFlags;
  534.     (**storage).outputCurrentFlags = info->outputCurrentFlags;
  535.     
  536.     return noErr;
  537. }
  538. pascal VideoDigitizerError    vdigGetCurrentFlags(vdigGlobals storage, long *inputCurrentFlag, long *outputCurrentFlag) 
  539. {
  540.     *inputCurrentFlag = (**storage).inputCurrentFlags;
  541.     *outputCurrentFlag = (**storage).outputCurrentFlags;
  542.     return noErr;
  543. }
  544.  
  545. pascal VideoDigitizerError vdigSetPlayThruOnOff(vdigGlobals storage, short state)
  546. {
  547.     if (!gDoesPlaythru)
  548.         return digiUnimpErr;
  549.  
  550.     (**storage).playThruOn = (state != 0);
  551.     return noErr;
  552. }
  553.  
  554. pascal VideoDigitizerError vdigSetPlayThruDestination(vdigGlobals storage, PixMapHandle dest, Rect *dr, MatrixRecord *m, RgnHandle mask)
  555. {
  556.     OSErr err;
  557.     short width, height;
  558.     Rect destRect;
  559.  
  560.     if (!dest || (!dr && !m))
  561.         return paramErr;
  562.  
  563.     if (dr)
  564.         destRect = *dr;
  565.     else {
  566.         if (GetMatrixType(m) > scaleTranslateMatrixType)
  567.             return matrixErr;
  568.         destRect = (**storage).digiRect;
  569.         TransformRect(m, &destRect, nil);
  570.     }
  571.  
  572.     // make sure the rectangle is ok
  573.     if (EmptyRect(&destRect))
  574.         return paramErr;
  575.  
  576.     if (mask && !gCanClip)
  577.         return paramErr;
  578.  
  579.     if (!validatePixMap(storage, dest))
  580.         return paramErr;
  581.  
  582.     if ((**storage).clipRgn) {
  583.         DisposeRgn((**storage).clipRgn);
  584.         (**storage).clipRgn = 0;
  585.     }
  586.  
  587.     if (mask) {
  588.         HandToHand((Handle *)&mask);
  589.         if (err = MemError()) return err;
  590.     }
  591.     (**storage).clipRgn = mask;
  592.     (**storage).clipOrigin = *(Point *)&destRect;
  593.  
  594.     {
  595.     Rect tempRect;
  596.  
  597.     tempRect = destRect;
  598.     MapRect(&tempRect, &(**storage).digiRect, &(**storage).maxSrcRect);            // convert to full frame
  599.     RectMatrix(&(**storage).matrix, &(**storage).maxSrcRect, &tempRect);        // make a matrix
  600.  
  601.     tempRect = (**storage).maxSrcRect;
  602.     TransformRect(&(**storage).matrix, &tempRect, 0);
  603.     width = tempRect.right - tempRect.left;
  604.     height = tempRect.bottom - tempRect.top;
  605.     }
  606.  
  607.     if (width < gMinWidth || width > gMaxWidth || height < gMinHeight || height > gMaxHeight)
  608.         return paramErr;
  609.  
  610. #if 0
  611.     if (width != gMaxWidth || height != gMaxHeight)
  612.         return paramErr;
  613. #endif
  614.  
  615.     if (!gCanScale) {
  616.         short i = 3;
  617.         short tempWidth = gMaxWidth;
  618.         short tempHeight = gMaxHeight;
  619.         Boolean ok;
  620.  
  621.         while (i--) {
  622.             ok = (width == tempWidth) && (height == tempHeight);
  623.             if (ok) break;
  624.             tempWidth >>= 1;
  625.             tempHeight >>= 1;
  626.         }
  627.         if (!ok)
  628.             return paramErr;
  629.     }
  630.  
  631.     if ((**storage).tempPort) {
  632.         if ((**dest).pixelSize != (**(**storage).tempPort->portPixMap).pixelSize)
  633.             tossOffscreen(storage);
  634.     }
  635.  
  636.     (**storage).playThruRect = destRect;
  637.     (**storage).playThruPixMap = dest;
  638.  
  639.     return noErr;
  640. }
  641.  
  642. // better checks for pixmap baseAddr matching could be done
  643. Boolean validatePixMap(vdigGlobals storage, PixMapHandle p)
  644. {
  645.     if ( !((**p).pixelSize & gDoesDepths) ) {
  646.         if (gCanDMA && ((**p).pixelSize & gDMADepths))
  647.             ;
  648.         else
  649.             return false;
  650.     }
  651.  
  652.     if (gCanDMA)                        // any other place is OK
  653.         return true;
  654.  
  655.     if ((**storage).gAttachedGDevice) {
  656.         // see if pixels are on the device
  657.         if ((**p).baseAddr == (**(**(**storage).gAttachedGDevice).gdPMap).baseAddr)
  658.             return true;
  659.     }
  660.  
  661.     if ((**storage).auxBuffer) {
  662.         if ((**p).baseAddr == (**(**storage).auxBuffer->portPixMap).baseAddr)
  663.             return true;
  664.     }
  665.  
  666.     if (!(**storage).gAttachedGDevice) return true;
  667.  
  668.     return false;
  669. }
  670.  
  671. pascal VideoDigitizerError vdigPreflightDestination(vdigGlobals storage, Rect *digitizerRect, PixMap **dest, Rect *destRect, MatrixRecord *m)
  672. {
  673.     //••  real code is required here in your vdig!!
  674.  
  675.     return noErr;
  676. }
  677.  
  678. pascal VideoDigitizerError vdigSetupBuffers(vdigGlobals storage, VdigBufferRecListHandle bufferList)
  679. {
  680.     OSErr err;
  681.     MatrixRecord matrix;
  682.     short i;
  683.     RgnHandle clipRgn;
  684.  
  685.     if (!bufferList)
  686.         return paramErr;
  687.  
  688.     if (!(**bufferList).count)
  689.         return paramErr;
  690.  
  691.     if ((**storage).bufferList) {
  692.         DisposHandle((Handle)(**storage).bufferList);
  693.         (**storage).bufferList = 0;
  694.     }
  695.  
  696.     if ((**storage).clipRgn) {
  697.         DisposeRgn((**storage).clipRgn);
  698.         (**storage).clipRgn = 0;
  699.     }
  700.  
  701.     if (!gCanClip && (**bufferList).mask)
  702.         return paramErr;
  703.  
  704.     if ((**bufferList).matrix)
  705.         matrix = *(**bufferList).matrix;
  706.  
  707.     // make a local copy of the buffer list
  708.     HandToHand((Handle *)&bufferList);
  709.     if (err = MemError()) return err;
  710.  
  711.     if (clipRgn = (**bufferList).mask) {
  712.         HandToHand((Handle *)&clipRgn);
  713.         if (err = MemError()) return err;
  714.         (**storage).clipOrigin = (**bufferList).list[0].location;
  715.     }
  716.  
  717.     (**storage).bufferList = bufferList;
  718.     (**storage).clipRgn = clipRgn;
  719.     (**storage).pendingAsyncBuffer = -1;
  720.     (**storage).matrix = matrix;
  721.  
  722.     for (i=0; i < (**bufferList).count; i++) {    
  723.         if (!validatePixMap(storage, (**bufferList).list[i].dest))
  724.             return paramErr;
  725.         // should check the point here too
  726.     }
  727.  
  728.     return noErr;
  729. }
  730.  
  731. pascal VideoDigitizerError vdigGrabOneFrameAsync(vdigGlobals storage, short buffer)
  732. {
  733.     VdigBufferRecListHandle bufferList;
  734.  
  735.     if (!gCanAsync)
  736.         return digiUnimpErr;
  737.  
  738.     if (!(bufferList = (**storage).bufferList))
  739.         return badCallOrder;
  740.  
  741.     if (buffer > (**bufferList).count)
  742.         return paramErr;
  743.  
  744.     if ((**storage).pendingAsyncBuffer != -1) {
  745.         short aBuf = (**storage).pendingAsyncBuffer;
  746.  
  747.         if (aBuf == buffer) DebugStr("\pasync grab into incomplete buffer");
  748.  
  749.         drawVideoFrame(storage, (**bufferList).list[aBuf].location, (**bufferList).list[aBuf].dest);
  750.     }
  751.  
  752.     (**storage).pendingAsyncBuffer = buffer;
  753.  
  754.     return noErr;
  755. }
  756.  
  757. pascal long    vdigDone(vdigGlobals storage, short buffer)
  758. {
  759.     vdigGlobalsPtr store = *storage;
  760.     VdigBufferRecListHandle bufferList;
  761.  
  762.     if (!gCanAsync)
  763.         return 0;
  764.  
  765.     if (!(bufferList = store->bufferList))
  766.         return 0;
  767.  
  768.     if (buffer > (**bufferList).count)
  769.         return 0;
  770.  
  771.     if (store->frameTimeStep && GetTimeBaseRate(store->timeBase)) {
  772.         if (GetTimeBaseTime(store->timeBase, gVideoTimeScale ? gVideoTimeScale : 600, nil) >= store->nextFrameTime)
  773.             store->nextFrameTime += store->frameTimeStep;
  774.         else
  775.             return false;
  776.     }
  777.  
  778.     if (store->pendingAsyncBuffer == buffer) {
  779.         drawVideoFrame(storage, (**bufferList).list[buffer].location, (**bufferList).list[buffer].dest);
  780.         store->pendingAsyncBuffer = -1;
  781.     }
  782.  
  783.     return true;
  784. }
  785.  
  786. /*
  787.     inputs garbage
  788. */
  789.  
  790. pascal VideoDigitizerError vdigGetNumberOfInputs(vdigGlobals storage, short *inputs)
  791. {
  792.     *inputs = 0;
  793.  
  794.     return noErr;
  795. }
  796.  
  797. pascal VideoDigitizerError vdigGetInputFormat(vdigGlobals storage, short input, short *format)
  798. {
  799.     if (input == 0) {
  800.         *format = ntscIn;
  801.         return noErr;
  802.     }
  803.     else
  804.         return paramErr;
  805. }
  806.  
  807. pascal VideoDigitizerError vdigSetInput(vdigGlobals storage, short input)
  808. {
  809.     if (input == 0)
  810.         return noErr;
  811.     else
  812.         return paramErr;
  813. }
  814.  
  815. pascal VideoDigitizerError vdigGetInput(vdigGlobals storage, short *input)
  816. {
  817.     *input = 0;
  818.  
  819.     return noErr;
  820. }
  821.  
  822. /*
  823.     compressed source stuff
  824. */
  825.  
  826. void tossCompressStuff(vdigGlobals storage)
  827. {
  828.     if ((**storage).compressSeq) {
  829.         CDSequenceEnd((**storage).compressSeq);
  830.         (**storage).compressSeq = 0;
  831.     }
  832.  
  833.     if ((**storage).compressGW) {
  834.         DisposeGWorld((**storage).compressGW);
  835.         (**storage).compressGW = 0;
  836.     }
  837.  
  838.     if ((**storage).compressBuffer) {
  839.         DisposPtr((**storage).compressBuffer);
  840.         (**storage).compressBuffer = 0;
  841.     }
  842.  
  843.     if ((**storage).desc) {
  844.         DisposHandle((Handle)(**storage).desc);
  845.         (**storage).desc = 0;
  846.     }
  847. }
  848.  
  849.  
  850. pascal VideoDigitizerError vdigSetCompression(vdigGlobals storage, OSType compressType, short depth, Rect *bounds,
  851.             CodecQ spatialQuality, CodecQ temporalQuality, long keyFrameRate)
  852. {
  853.     OSErr err;
  854.     GWorldPtr gw = 0;
  855.     long bufSize;
  856.     Ptr p;
  857.     ImageDescription ** tempImageDesc;
  858.     ImageSequence tempSeqId;
  859.  
  860.     if (!gDoesCompress)
  861.         return digiUnimpErr;
  862.  
  863.     tossCompressStuff(storage);
  864.  
  865.     if (compressType == 'vpza')
  866.         compressType = 'rpza';
  867.  
  868.     // see if we handle this compression
  869.     if (compressType && gOnlyCompressType && 
  870.         (compressType != gOnlyCompressType))
  871.         return noCodecErr;
  872.  
  873.     if (!compressType) {
  874.         compressType = gOnlyCompressType ? gOnlyCompressType : 'rpza';
  875.         spatialQuality = codecNormalQuality;
  876.         temporalQuality = 0;
  877.         keyFrameRate = 0;
  878.     }
  879.  
  880.     (**storage).compressType = compressType;
  881.     (**storage).compressDepth = depth ? depth : 16;
  882.     (**storage).compressRect = *bounds;
  883.     (**storage).spatialQuality = spatialQuality;
  884.     (**storage).temporalQuality = temporalQuality;
  885.     (**storage).keyFrameRate = keyFrameRate;
  886.  
  887.     if (compressType == -1)
  888.         return noErr;
  889.  
  890.     {
  891.     Rect tempRect;
  892.  
  893.     tempRect = *bounds;
  894.     MapRect(&tempRect, &(**storage).digiRect, &(**storage).maxSrcRect);            // convert to full frame
  895.     RectMatrix(&(**storage).matrix, &(**storage).maxSrcRect, &tempRect);        // make a matrix
  896.     }
  897.  
  898.     err = NewGWorld(&gw, depth, bounds, 0, 0, 0);
  899.     if (err) goto bail;
  900.     (**storage).compressGW = gw;
  901.     LockPixels(gw->portPixMap);
  902.  
  903.     err = GetMaxCompressionSize(gw->portPixMap, bounds, depth, spatialQuality, compressType, bestSpeedCodec, &bufSize);
  904.     if (err) goto bail;
  905.  
  906.     p = NewPtr(bufSize);
  907.     if (err = MemError())  goto bail;
  908.     (**storage).compressBuffer = p;
  909.  
  910.     tempImageDesc = (ImageDescription **)NewHandle(sizeof(ImageDescription));
  911.     if (err = MemError()) goto bail;
  912.     (**storage).desc = tempImageDesc;
  913.  
  914.     // fill this out for now.. mark will help us out later
  915.     (**tempImageDesc).temporalQuality = temporalQuality;
  916.     (**tempImageDesc).spatialQuality = spatialQuality;
  917.     (**tempImageDesc).width = bounds->right - bounds->left;
  918.     (**tempImageDesc).height = bounds->bottom - bounds->top;
  919.     (**tempImageDesc).depth = (compressType == 'rpza') ? 16 : depth;
  920.     (**tempImageDesc).cType = compressType;
  921.     (**tempImageDesc).hRes = 0x00480000;
  922.     (**tempImageDesc).vRes = 0x00480000;
  923.  
  924.     err = CompressSequenceBegin(&tempSeqId,
  925.                     gw->portPixMap, (PixMap **)0,
  926.                     bounds, (Rect *)0,
  927.                     depth, compressType, bestSpeedCodec, spatialQuality, 
  928.                     temporalQuality, keyFrameRate, (CTabHandle )0,
  929.                     codecFlagUpdatePrevious, tempImageDesc );
  930.     if (err) goto bail;
  931.  
  932.     (**storage).compressSeq = tempSeqId;
  933.  
  934. bail:
  935.     if (err)
  936.         tossCompressStuff(storage);
  937.  
  938.     return err;
  939. }
  940.  
  941. pascal VideoDigitizerError vdigCompressOneFrameAsync(vdigGlobals storage)
  942. {
  943.     if (!gDoesCompress)
  944.         return digiUnimpErr;
  945.  
  946.     if (!(**storage).compressSeq)
  947.         return badCallOrder;
  948.  
  949.     // draw the offscreen now, compress later...
  950.     drawVideoFrame(storage, *(Point *)&(**storage).compressRect, (**storage).compressGW->portPixMap);
  951.  
  952.     return noErr;
  953. }
  954.  
  955. pascal VideoDigitizerError vdigCompressDone(vdigGlobals storage, Boolean *done, Ptr *theData, long *dataSize, unsigned char *similarity, TimeRecord *tr)
  956. {
  957.     vdigGlobalsPtr store = *storage;
  958.     OSErr err;
  959.     Rect r;
  960.  
  961.     *done = true;
  962.  
  963.     if (!gDoesCompress)
  964.         return digiUnimpErr;
  965.  
  966.     if (!store->compressSeq)
  967.         return badCallOrder;
  968.  
  969.     if (store->frameTimeStep && GetTimeBaseRate(store->timeBase)) {
  970.         if (GetTimeBaseTime(store->timeBase, gVideoTimeScale ? gVideoTimeScale : 600, nil) >= store->nextFrameTime)
  971.             store->nextFrameTime += store->frameTimeStep;
  972.         else {
  973.             *done = false;
  974.             return noErr;
  975.         }
  976.     }
  977.  
  978.     r = store->compressRect;
  979.     err = (OSErr)CompressSequenceFrame(store->compressSeq, store->compressGW->portPixMap, &r,
  980.                             codecFlagUpdatePrevious | (store->forceKeyFrame ? codecFlagForceKeyFrame : 0),
  981.                             store->compressBuffer, dataSize, similarity, (CompletionProcRecordPtr)0);
  982.     store = *storage;
  983.     *theData = store->compressBuffer;
  984.  
  985.     store->forceKeyFrame = false;
  986.  
  987.     GetTimeBaseTime(store->timeBase, 30, tr);
  988.  
  989.     return err;
  990. }
  991.  
  992. pascal VideoDigitizerError vdigReleaseCompressBuffer(vdigGlobals storage, Ptr theBufffer)
  993. {
  994.     if (!gDoesCompress)
  995.         return digiUnimpErr;
  996.  
  997.     if (!(**storage).compressSeq)
  998.         return badCallOrder;
  999.  
  1000.     //•• could actually track this...
  1001.     //•• could pound part of buffer to 0 or something
  1002.  
  1003.     return noErr;
  1004. }
  1005.  
  1006.  
  1007. pascal VideoDigitizerError vdigGetImageDescription(vdigGlobals storage, ImageDescriptionHandle desc)
  1008. {
  1009.     OSErr err = noErr;
  1010.  
  1011.     if (!gDoesCompress)
  1012.         return digiUnimpErr;
  1013.  
  1014.     if ((**storage).desc) {
  1015.         long dataSize;
  1016.  
  1017.         SetHandleSize((Handle)desc, dataSize = GetHandleSize((Handle)(**storage).desc));
  1018.         if (err = MemError()) goto bail;
  1019.         BlockMove((Ptr)*(**storage).desc, (Ptr)*desc, dataSize);
  1020.     }
  1021.     else
  1022.         err = badCallOrder;
  1023.  
  1024. bail:
  1025.     return err;
  1026. }
  1027.  
  1028. pascal VideoDigitizerError vdigResetCompressSequence(vdigGlobals storage)
  1029. {
  1030.     OSErr err = noErr;
  1031.  
  1032.     if (!gDoesCompress)
  1033.         return digiUnimpErr;
  1034.  
  1035.     (**storage).forceKeyFrame = true;
  1036.  
  1037.     return err;
  1038. }
  1039.  
  1040. pascal VideoDigitizerError vdigSetCompressionOnOff(vdigGlobals storage, Boolean newState)
  1041. {
  1042.     OSErr err = noErr;
  1043.  
  1044.     if (!gDoesCompress)
  1045.         return digiUnimpErr;
  1046.  
  1047.     if (newState != (**storage).compressOn) {
  1048.         (**storage).compressOn = newState;
  1049.         if (!(**storage).compressOn)
  1050.             tossCompressStuff(storage);
  1051.     }
  1052.  
  1053.     return err;
  1054. }
  1055.  
  1056. pascal VideoDigitizerError vdigGetCompressionTypes(vdigGlobals storage, VDCompressionListHandle h)
  1057. {
  1058.     CodecInfo info;
  1059.     CodecType cType;
  1060.     CodecComponent codec;
  1061.     VDCompressionListPtr p;
  1062.  
  1063.     GetCodecInfo(&info, 'rpza',  0);
  1064.     SetHandleSize((Handle)h, sizeof(VDCompressionList));
  1065.     p = &(*h)[0];
  1066.     BlockMove(info.typeName, p->typeName, 32);
  1067.     p->typeName[++p->typeName[0]] = ' ';
  1068.     p->typeName[++p->typeName[0]] = 'V';
  1069.     p->typeName[++p->typeName[0]] = 'D';
  1070.     p->typeName[++p->typeName[0]] = 'I';
  1071.     p->typeName[++p->typeName[0]] = 'G';
  1072.     BlockMove(p->typeName, p->name, 64);
  1073.     p->codec = 0;
  1074.     p->cType = 'rpza';
  1075.     p->formatFlags = info.formatFlags;
  1076.     p->compressFlags = info.compressFlags;
  1077.  
  1078.     return noErr;
  1079. }
  1080.  
  1081. pascal VideoDigitizerError vdigSetTimeBase(vdigGlobals storage, TimeBase t)
  1082. {
  1083.     (**storage).timeBase = t;
  1084.     return noErr;
  1085. }
  1086.  
  1087. pascal VideoDigitizerError vdigSetFrameRate(vdigGlobals storage, Fixed framesPerSecond)
  1088. {
  1089.     vdigGlobalsPtr store = *storage;
  1090.  
  1091.     if (!gDoesFrameRate)
  1092.         return digiUnimpErr;
  1093.  
  1094.     if (framesPerSecond < 0)
  1095.         return paramErr;
  1096.  
  1097.     store->nextFrameTime = store->frameTimeStep = 0;
  1098.     if (framesPerSecond)
  1099.         store->frameTimeStep = FixDiv(gVideoTimeScale ? gVideoTimeScale : 600, framesPerSecond);
  1100.  
  1101.     return noErr;
  1102. }
  1103.  
  1104. pascal VideoDigitizerError vdigGetDMADepths(vdigGlobals storage, long *depthArray, long *preferredDepth)
  1105. {
  1106.     if (!gCanDMA)
  1107.         return paramErr;
  1108.  
  1109.     *depthArray = gDMADepths;
  1110. //    *preferredDepth = gDMADepths & 16;
  1111.     *preferredDepth = 40;
  1112. // kck    *preferredDepth = 8;
  1113.  
  1114.     return noErr;
  1115. }
  1116.  
  1117. pascal VideoDigitizerError vdigGetPreferredTimeScale(vdigGlobals storage, TimeScale *preferred)
  1118. {
  1119.     if (gVideoTimeScale) {
  1120.         *preferred = gVideoTimeScale;
  1121.         return noErr;
  1122.     }
  1123.     else
  1124.         return badComponentSelector;
  1125. }
  1126.  
  1127.